该方法在view依附于window时被调用,此时,view已经拥有了surface并且准备开始进行绘制了。这里提到的surface,其定义为Handle onto a raw buffer that is being managed by the screen compositor[1],也就是屏幕生成器管理的原始缓冲区的句柄,用这个句柄可以获得用来画图的canvas以及存放当前窗口缓冲数据的原始缓冲区。这里的屏幕生成器概念比较底层,比较典型的屏幕生成器有SurfaceFlinger和Skia,SurfaceFlinger是唯一一个可以修改显示内容的服务,SurfaceFlinger使用OpenGL和Hardware Composer去管理surface[2]。其中,OpenGL是Open Graphics Library。它是一个跨平台的API规范,包含了一系列规范的3D graphics接口。而OpenGL ES则是为OpenGL嵌入式设备设计的规范[3]。每个window都对应一个Surface,而每个view都要画在这个surface上。同时注意surfaceView,不同于surface,surfaceView是一个具体的view,他和view的具体差别在于surfaceView并不是在主线程上进行绘制,他是另起一个线程进行绘制。
// first clears the measured dimension flag mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
resolveRtlPropertiesIfNeeded();
int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) { // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } else { long value = mMeasureCache.valueAt(cacheIndex); // Casting a long to int drops the high 32 bits, no mask needed setMeasuredDimension((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; }
// flag not set, setMeasuredDimension() was not invoked, we raise // an exception to warn the developer if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { thrownew IllegalStateException("onMeasure() did not set the" + " measured dimension by calling" + " setMeasuredDimension()"); }
For views that contain nine-patch background images, you can now specify that they should be aligned with neighboring views based on the “optical” bounds of the background image rather than the “clip” bounds of the view. For example, figures 1 and 2 each show the same layout, but the version in figure 1 is using clip bounds (the default behavior), while figure 2 is using optical bounds. Because the nine-patch images used for the button and the photo frame include padding around the edges, they don’t appear to align with each other or the text when using clip bounds.
sIgnoreMeasureCache = targetSdkVersion < KITKAT; 当小于4.4时该标志为false) if (cacheIndex < 0 || sIgnoreMeasureCache) { // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } else { long value = mMeasureCache.valueAt(cacheIndex); // Casting a long to int drops the high 32 bits, no mask needed setMeasuredDimension((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; }
public staticint getDefaultSize(int size, int measureSpec) { intresult = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) { caseMeasureSpec.UNSPECIFIED: result = size; break; caseMeasureSpec.AT_MOST: caseMeasureSpec.EXACTLY: result = specSize; break; } returnresult; }
/* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */